<?php

namespace Mlym\CodeGeneration\InitGeneration\Authorization\Method;

use EasySwoole\Component\Context\ContextManager;
use EasySwoole\EasySwoole\Config;
use EasySwoole\Http\Request;
use EasySwoole\Jwt\Jwt;
use Mlym\CodeGeneration\ClassGeneration\MethodAbstract;

class VerifyToken extends MethodAbstract
{
    function addMethodBody()
    {
        $this->classGeneration->getPhpNamespace()->addUse('App\Exception\AuthorizationException');
        $this->classGeneration->getPhpNamespace()->addUse(ContextManager::class);
        $this->classGeneration->getPhpNamespace()->addUse(Jwt::class);
        $this->method->addParameter('request')->setType(Request::class);
        $this->method
            ->setReturnType('void')
            ->setBody(<<<BODY
/**
 * 获取校验的Action路径
 */
\$pathInfo = \$request->getServerParams()['path_info'] ?? "";
/**
 * 对不在IgnoreAction中的Action进行token校验
 */
if (!in_array(\$pathInfo, \$this->ignoreAction)) {

    /**
     * 获取Header->Authorization中的Token
     */
    \$token = '';
    \$authorization = \$request->getHeader('authorization')[0] ?? '';
    if (preg_match('/Bearer\s(\S+)/', \$authorization, \$matches)) {
        \$token = \$matches[1];
    }

    /**
     * Token校验
     * 1. Token 非空校验
     * 2. Token header & Token payload 非空校验
     * 3. Token Signature 校验
     * 4. Token expires 校验
     */
    try {
        if (empty(\$token)) {
            throw new AuthorizationException("JWT:token is required.", 401);
        }
        \$jwtObject = Jwt::getInstance()->setSecretKey(\$this->secretKey)->decode(\$token);
        switch (\$jwtObject->getStatus()) {
            case  -1:
                throw new AuthorizationException("JWT:token invalid.", 401);
            case  -2:
                throw new AuthorizationException("JWT:token expires.", 401);
        }
        if (\$jwtObject->getStatus() == 1) {
            \$data = \$jwtObject->getData();
            foreach (\$this->dataFields as \$field) {
                ContextManager::getInstance()->set(\$field, \$data[\$field] ?? '');
            }
        } else {
            throw new AuthorizationException("JWT:token decode exception.", 401);
        }
    } catch (\Exception \$exception) {
        throw new AuthorizationException("JWT:" . \$exception->getMessage(), 401);
    }
}
BODY
            );
    }

    function getMethodName(): string
    {
        return 'verifyToken';
    }

    public function addComment()
    {
        $this->method->addComment(<<<BODY
校验Token
@param Request \$request 请求对象
@throws AuthorizationException
BODY
        );
    }
}